package com.qixin.storage;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.qixin.utils.FastDFSClient;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.exception.JeecgBootException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.HandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author Created by wmf at 2019-11-24
 */

@Api(tags="fastdfs文件服务器")
@RestController
@RequestMapping(value = "/api/fastdfs",produces="application/json;charset=UTF-8")
@Slf4j
public class FastDFSController {

    @Autowired
    FastDFSClient fastDFSClient;

    /**
     * 单文件上传
     */
    @AutoLog(value = "fastdfs单文件上传")
    @ApiOperation(value="单文件上传", notes="单文件上传")
    @PostMapping("/upload")
    public Result<?> upload(@RequestParam("file") MultipartFile file) throws Exception {
        if (file.isEmpty()) {
            throw new JeecgBootException("上传文件不能为空");
        }
        //上传文件
        String url = fastDFSClient.uploadFile(file);

        return Result.OK(url ,file.getOriginalFilename() );
    }

    //多文件上传
    @AutoLog(value = "fastdfs多文件上传")
    @ApiOperation(value="多文件上传", notes="多文件上传")
    @PostMapping(value = "/batch_upload")
    public Result<?> handleFileUpload(HttpServletRequest request) throws Exception {
        List<MultipartFile> files = ((MultipartHttpServletRequest) request)
                .getFiles("file");
        MultipartFile file = null;
        List<String>list=new ArrayList<>();
        for (int i = 0; i < files.size(); ++i) {
            file = files.get(i);
            if (!file.isEmpty()) {
                //上传文件
                String url = fastDFSClient.uploadFile(file);
                list.add(url);

            }
        }
        return Result.OK("上传成功！", list);
    }

    /**
     * 删除文件
     */
    @AutoLog(value = "fastdfs删除文件")
    @ApiOperation(value="删除文件", notes="删除文件")
    @PostMapping("/delete")
    public Result<?> delete(@RequestParam("fileUrl") String fileUrl) throws Exception {
        if (StringUtils.isNotBlank(fileUrl)) {
            throw new JeecgBootException("文件路径不能为空");
        }
        fastDFSClient.deleteFile(fileUrl);

        return Result.ok("删除成功！");
    }

    /**
     * 删除文件
     */
    @ApiOperation(value="下载文件", notes="下载文件")
    @GetMapping(value = "/download/**")
    public void download(HttpServletRequest request, HttpServletResponse response) {
        // ISO-8859-1 ==> UTF-8 进行编码转换
        String imgPath = extractPathFromPattern(request);
        if (StrUtil.isBlank(imgPath) || imgPath == "null") {
            return;
        }

        // 其余处理略
        InputStream inputStream = null;
        OutputStream outputStream = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            imgPath = imgPath.replace("..", "");
            if (imgPath.endsWith(",")) {
                imgPath = imgPath.substring(0, imgPath.length() - 1);
            }

            //2.下载操作
            //方式一 文件id下载
            String[] strArray = imgPath.split("\\.");
            int suffixIndex = strArray.length -1;
            byte[] bytes = fastDFSClient.downloadFile(imgPath);//记得要传文件id返回字节流
            String fileName = DateUtil.now() + "." + strArray[suffixIndex];
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + new String(fileName.getBytes("UTF-8"), "iso-8859-1"));
            response.setContentLength(bytes.length);
            inputStream = new ByteArrayInputStream(bytes);
            outputStream = response.getOutputStream();
            bis = new BufferedInputStream(inputStream);
            bos = new BufferedOutputStream(outputStream);
            byte[] buff = new byte[1024];
            int bytesRead;
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);

            }
            outputStream.flush();
        } catch (IOException e) {
            log.error("预览文件失败" + e.getMessage());
            response.setStatus(404);
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 把指定URL后的字符串全部截断当成参数
     * 这么做是为了防止URL中包含中文或者特殊字符（/等）时，匹配不了的问题
     *
     * @param request
     * @return
     */
    private static String extractPathFromPattern(final HttpServletRequest request) {
        String path = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
        String bestMatchPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
        return new AntPathMatcher().extractPathWithinPattern(bestMatchPattern, path);
    }
}
